package database

import (
	"context"
	"sync"
	"time"

	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"

	"changeme/internal/models"
)

// Manager 数据库管理器实现
type Manager struct {
	storage     ConfigStorage
	factory     DriverFactory
	pool        ConnectionPool
	password    PasswordManager
	connections map[string]DatabaseDriver
	mutex       sync.RWMutex
	logger      *logrus.Logger
}

// NewManager 创建数据库管理器实例
func NewManager(storage ConfigStorage, factory DriverFactory, pool ConnectionPool, password PasswordManager) *Manager {
	logger := logrus.New()
	logger.SetLevel(logrus.DebugLevel) // 设置为DEBUG级别以便调试密码问题

	return &Manager{
		storage:     storage,
		factory:     factory,
		pool:        pool,
		password:    password,
		connections: make(map[string]DatabaseDriver),
		logger:      logger,
	}
}

// SaveConfig 保存数据库配置
func (m *Manager) SaveConfig(config *models.DatabaseConfig) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 创建配置副本以避免修改原始配置
	saveConfig := *config

	m.logger.WithFields(logrus.Fields{
		"config_name":     saveConfig.Name,
		"has_password":    saveConfig.Password != "",
		"password_length": len(saveConfig.Password),
	}).Debug("Saving new config")

	// 暂时不加密密码，直接保存明文
	// TODO: 实现更可靠的密码加密方案
	if saveConfig.Password != "" {
		m.logger.WithField("password_length", len(saveConfig.Password)).Debug("Saving password as plaintext")
	}

	// 生成ID（如果没有）
	if err := saveConfig.BeforeCreate(); err != nil {
		return errors.Wrap(err, "failed to generate config ID")
	}

	// 保存配置
	if err := m.storage.Save(&saveConfig); err != nil {
		return errors.Wrap(err, "failed to save config")
	}

	// 更新原始配置的ID（用于返回给前端）
	config.ID = saveConfig.ID

	m.logger.WithField("config_id", saveConfig.ID).Info("Database config saved")
	return nil
}

// GetConfig 获取数据库配置
func (m *Manager) GetConfig(id string) (*models.DatabaseConfig, error) {
	config, err := m.storage.Get(id)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get config")
	}

	m.logger.WithFields(logrus.Fields{
		"config_id":       config.ID,
		"config_name":     config.Name,
		"has_password":    config.Password != "",
		"password_length": len(config.Password),
	}).Debug("Retrieved config from storage")

	// 暂时不解密密码，直接返回明文
	// TODO: 实现更可靠的密码加密方案
	if config.Password != "" {
		m.logger.WithFields(logrus.Fields{
			"config_id":       config.ID,
			"password_length": len(config.Password),
		}).Debug("Returning password as plaintext")
	} else {
		m.logger.WithField("config_id", config.ID).Debug("No password stored")
	}

	return config, nil
}

// GetAllConfigs 获取所有数据库配置
func (m *Manager) GetAllConfigs() ([]*models.DatabaseConfig, error) {
	configs, err := m.storage.GetAll()
	if err != nil {
		return nil, errors.Wrap(err, "failed to get all configs")
	}

	// 暂时返回明文密码，便于前端使用
	// TODO: 实现更安全的密码处理方案
	m.logger.WithField("config_count", len(configs)).Debug("Retrieved all configs with plaintext passwords")

	return configs, nil
}

// DeleteConfig 删除数据库配置
func (m *Manager) DeleteConfig(id string) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 1. 获取配置信息，检查是否为默认配置
	config, err := m.storage.Get(id)
	if err != nil {
		if errors.Is(err, ErrConfigNotFound) {
			// 配置不存在，直接返回成功
			m.logger.WithField("config_id", id).Info("Config not found, nothing to delete")
			return nil
		}
		return errors.Wrap(err, "failed to get config before deletion")
	}

	isDefault := config.IsDefault
	m.logger.WithFields(logrus.Fields{
		"config_id":   id,
		"config_name": config.Name,
		"is_default":  isDefault,
	}).Info("Preparing to delete database connection")

	// 2. 关闭相关连接 - 使用单独的锁避免死锁
	m.mutex.Unlock() // 暂时释放锁
	err = m.CloseConnection(id)
	m.mutex.Lock() // 重新获取锁

	if err != nil {
		m.logger.WithError(err).WithField("config_id", id).Warn("Failed to close connection before deleting config")
		// 继续执行，不要因为关闭连接失败而中止删除操作
	}

	// 3. 删除配置
	if err := m.storage.Delete(id); err != nil {
		return errors.Wrap(err, "failed to delete config")
	}

	// 4. 如果是默认配置，尝试设置新的默认配置
	if isDefault {
		m.logger.Info("Deleted config was the default, trying to set a new default")
		configs, err := m.storage.GetAll()
		if err != nil {
			m.logger.WithError(err).Warn("Failed to get all configs after deleting default")
		} else if len(configs) > 0 {
			// 选择第一个配置作为新的默认配置
			newDefaultID := configs[0].ID
			if err := m.storage.SetDefault(newDefaultID); err != nil {
				m.logger.WithError(err).WithField("new_default_id", newDefaultID).
					Warn("Failed to set new default config")
			} else {
				m.logger.WithField("new_default_id", newDefaultID).
					Info("Set new default config after deleting previous default")
			}
		}
	}

	// 5. 清理其他资源
	// 从连接缓存中移除
	delete(m.connections, id)

	m.logger.WithFields(logrus.Fields{
		"config_id":   id,
		"config_name": config.Name,
	}).Info("Database config successfully deleted")
	return nil
}

// UpdateConfig 更新数据库配置
func (m *Manager) UpdateConfig(config *models.DatabaseConfig) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 获取现有配置
	existingConfig, err := m.storage.Get(config.ID)
	if err != nil {
		return errors.Wrap(err, "failed to get existing config")
	}

	// 创建配置副本以避免修改原始配置
	updateConfig := *config

	m.logger.WithFields(logrus.Fields{
		"config_id":           config.ID,
		"config_name":         config.Name,
		"new_password_empty":  config.Password == "",
		"new_password_length": len(config.Password),
		"old_password_length": len(existingConfig.Password),
	}).Debug("Updating config with password handling")

	// 处理密码更新（暂时不加密）
	// TODO: 实现更可靠的密码加密方案
	if updateConfig.Password != "" {
		// 直接使用明文密码
		m.logger.WithField("password_length", len(updateConfig.Password)).Debug("Updating password as plaintext")
	} else {
		// 如果密码为空，保留原有的密码
		m.logger.Debug("No new password provided, keeping existing password")
		updateConfig.Password = existingConfig.Password
	}

	// 更新配置
	if err := m.storage.Update(&updateConfig); err != nil {
		return errors.Wrap(err, "failed to update config")
	}

	// 如果连接存在，关闭它以便下次使用新配置
	if _, exists := m.connections[config.ID]; exists {
		if err := m.CloseConnection(config.ID); err != nil {
			m.logger.WithError(err).WithField("config_id", config.ID).Warn("Failed to close connection after config update")
		}
	}

	m.logger.WithField("config_id", config.ID).Info("Database config updated")
	return nil
}

// SetDefaultConfig 设置默认数据库配置
func (m *Manager) SetDefaultConfig(id string) error {
	return m.storage.SetDefault(id)
}

// GetDefaultConfig 获取默认数据库配置
func (m *Manager) GetDefaultConfig() (*models.DatabaseConfig, error) {
	config, err := m.storage.GetDefault()
	if err != nil {
		return nil, errors.Wrap(err, "failed to get default config")
	}

	// 暂时不解密密码，直接返回明文
	// TODO: 实现更可靠的密码加密方案
	if config != nil && config.Password != "" {
		m.logger.WithField("password_length", len(config.Password)).Debug("Returning default config password as plaintext")
	}

	return config, nil
}

// GetConnection 获取数据库连接
func (m *Manager) GetConnection(configID string) (DatabaseDriver, error) {
	m.mutex.RLock()
	if driver, exists := m.connections[configID]; exists {
		m.mutex.RUnlock()
		if driver.IsConnected() {
			return driver, nil
		}
	}
	m.mutex.RUnlock()

	// 连接不存在或已断开，创建新连接
	config, err := m.GetConfig(configID)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get config for connection")
	}

	return m.CreateConnection(config)
}

// CreateConnection 创建数据库连接
func (m *Manager) CreateConnection(config *models.DatabaseConfig) (DatabaseDriver, error) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 检查是否已存在连接
	if driver, exists := m.connections[config.ID]; exists {
		if driver.IsConnected() {
			return driver, nil
		}
		// 连接已断开，移除旧连接
		delete(m.connections, config.ID)
	}

	// 创建新驱动
	driver, err := m.factory.CreateDriver(config.Type)
	if err != nil {
		return nil, errors.Wrap(err, "failed to create driver")
	}

	// 连接数据库
	if err := driver.Connect(config); err != nil {
		return nil, errors.Wrap(err, "failed to connect to database")
	}

	// 保存连接
	m.connections[config.ID] = driver

	// 更新最后使用时间
	now := time.Now()
	config.LastUsedAt = &now
	if err := m.storage.Update(config); err != nil {
		m.logger.WithError(err).WithField("config_id", config.ID).Warn("Failed to update last used time")
	}

	m.logger.WithFields(logrus.Fields{
		"config_id": config.ID,
		"db_type":   config.Type,
		"host":      config.Host,
	}).Info("Database connection created")

	return driver, nil
}

// CloseConnection 关闭数据库连接
func (m *Manager) CloseConnection(configID string) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	driver, exists := m.connections[configID]
	if !exists {
		return nil // 连接不存在，视为成功
	}

	if err := driver.Disconnect(); err != nil {
		m.logger.WithError(err).WithField("config_id", configID).Error("Failed to disconnect from database")
		return errors.Wrap(err, "failed to disconnect from database")
	}

	delete(m.connections, configID)
	m.logger.WithField("config_id", configID).Info("Database connection closed")
	return nil
}

// CloseAllConnections 关闭所有数据库连接
func (m *Manager) CloseAllConnections() error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	var lastError error
	for configID, driver := range m.connections {
		if err := driver.Disconnect(); err != nil {
			m.logger.WithError(err).WithField("config_id", configID).Error("Failed to disconnect from database")
			lastError = err
		}
	}

	m.connections = make(map[string]DatabaseDriver)
	m.logger.Info("All database connections closed")
	return lastError
}

// GetConnectionStatus 获取连接状态
func (m *Manager) GetConnectionStatus(configID string) (*models.ConnectionStatus, error) {
	m.mutex.RLock()
	driver, exists := m.connections[configID]
	m.mutex.RUnlock()

	status := &models.ConnectionStatus{
		ConfigID:    configID,
		IsConnected: false,
		ConnectedAt: time.Now(),
	}

	if !exists {
		status.Error = "Connection not found"
		return status, nil
	}

	status.IsConnected = driver.IsConnected()
	if status.IsConnected {
		if err := driver.Ping(); err != nil {
			status.IsConnected = false
			status.Error = err.Error()
		} else {
			version, err := driver.GetVersion()
			if err != nil {
				m.logger.WithError(err).WithField("config_id", configID).Warn("Failed to get database version")
			} else {
				status.Version = version
			}
		}
	}

	return status, nil
}

// TestConnection 测试数据库连接
func (m *Manager) TestConnection(config *models.DatabaseConfig) error {
	// 创建配置副本以避免修改原始配置
	testConfig := *config

	m.logger.WithFields(logrus.Fields{
		"config_name":     testConfig.Name,
		"username":        testConfig.Username,
		"host":            testConfig.Host,
		"port":            testConfig.Port,
		"has_password":    testConfig.Password != "",
		"password_length": len(testConfig.Password),
	}).Debug("Testing connection with config")

	// 暂时不解密密码，直接使用明文
	// TODO: 实现更可靠的密码加密方案
	if testConfig.Password != "" {
		m.logger.WithFields(logrus.Fields{
			"password_length": len(testConfig.Password),
		}).Debug("Using password as plaintext for test connection")
	} else {
		m.logger.Debug("No password provided in config")
	}

	driver, err := m.factory.CreateDriver(testConfig.Type)
	if err != nil {
		return errors.Wrap(err, "failed to create driver for test")
	}

	if err := driver.Connect(&testConfig); err != nil {
		return errors.Wrap(err, "failed to connect for test")
	}
	defer driver.Disconnect()

	if err := driver.Ping(); err != nil {
		return errors.Wrap(err, "failed to ping database")
	}

	m.logger.WithField("config_name", testConfig.Name).Info("Test connection successful")
	return nil
}

// min 返回两个整数中的较小值
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// 数据库操作方法（通过配置ID）

// ListDatabases 列出数据库
func (m *Manager) ListDatabases(configID string) ([]models.DatabaseInfo, error) {
	driver, err := m.GetConnection(configID)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	return driver.ListDatabases(ctx)
}

// ListTables 列出表
func (m *Manager) ListTables(configID, database string) ([]models.TableInfo, error) {
	driver, err := m.GetConnection(configID)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	return driver.ListTables(ctx, database)
}

// GetTableColumns 获取表列信息
func (m *Manager) GetTableColumns(configID, database, table string) ([]models.ColumnInfo, error) {
	driver, err := m.GetConnection(configID)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	return driver.GetTableColumns(ctx, database, table)
}

// GetTableIndexes 获取表索引信息
func (m *Manager) GetTableIndexes(configID, database, table string) ([]models.IndexInfo, error) {
	driver, err := m.GetConnection(configID)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	return driver.GetTableIndexes(ctx, database, table)
}

// ExecuteQuery 执行查询
func (m *Manager) ExecuteQuery(configID, query string, args ...interface{}) (*models.QueryResult, error) {
	driver, err := m.GetConnection(configID)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()

	return driver.ExecuteQuery(ctx, query, args...)
}

// ExecuteNonQuery 执行非查询语句
func (m *Manager) ExecuteNonQuery(configID, query string, args ...interface{}) (int64, error) {
	driver, err := m.GetConnection(configID)
	if err != nil {
		return 0, err
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()

	return driver.ExecuteNonQuery(ctx, query, args...)
}
